package com.xyzk.diagnose.tools;

public class Security {
	/**
	 * CRC16标准算法
	 * @param data 需要校验的字节数组
	 * @param datasize 校验字节数组的大小
	 * @param checksum 校验码，两个字节
	 */
	public static void Crc16(byte[] data, int datasize, byte[] checksum){
		int crc = 0xffff;
		int temp = 0;
		int i = 0;
		int[] crctab = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
				0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
				0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
				0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
				0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
				0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
				0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
				0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
				0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
				0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
				0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
				0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
				0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
				0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
				0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
				0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
				0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
				0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
				0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
				0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
				0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
				0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
				0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
				0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
				0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
				0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
				0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
				0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
				0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
				0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
				0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
				0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
		for ( i = 0; i < datasize; i++){
			temp=((crc>>8) ^ data[i]) & 0xff;
			crc=((crc<<8) ^ crctab[temp]) & 0xFFFF;
		}
		checksum[0] = (byte) ((byte) (crc >> 8) & 0xFF);
		checksum[1] = (byte) ((byte) (crc & 0xFF));
	}

	/**
	 * CRC32标准算法
	 * @param data 需要校验的字节数组
	 * @param datasize 校验字节数组的大小
	 * @param checksum 校验码,四个字节
	 */
	public static void Crc32(byte [] pData, int size, byte[] checksum){
		int[] crc32Tab = { 0x00000000 , 0x77073096 ,
				0xEE0E612C ,  0x990951BA ,  0x076DC419 ,  0x706AF48F ,  0xE963A535 ,
				0x9E6495A3 ,  0x0EDB8832 ,  0x79DCB8A4 ,  0xE0D5E91E ,  0x97D2D988 ,
				0x09B64C2B ,  0x7EB17CBD ,  0xE7B82D07 ,  0x90BF1D91 ,  0x1DB71064 ,
				0x6AB020F2 ,  0xF3B97148 ,  0x84BE41DE ,  0x1ADAD47D ,  0x6DDDE4EB ,
				0xF4D4B551 ,  0x83D385C7 ,  0x136C9856 ,  0x646BA8C0 ,  0xFD62F97A ,
				0x8A65C9EC ,  0x14015C4F ,  0x63066CD9 ,  0xFA0F3D63 ,  0x8D080DF5 ,
				0x3B6E20C8 ,  0x4C69105E ,  0xD56041E4 ,  0xA2677172 ,  0x3C03E4D1 ,
				0x4B04D447 ,  0xD20D85FD ,  0xA50AB56B ,  0x35B5A8FA ,  0x42B2986C ,
				0xDBBBC9D6 ,  0xACBCF940 ,  0x32D86CE3 ,  0x45DF5C75 ,  0xDCD60DCF ,
				0xABD13D59 ,  0x26D930AC ,  0x51DE003A ,  0xC8D75180 ,  0xBFD06116 ,
				0x21B4F4B5 ,  0x56B3C423 ,  0xCFBA9599 ,  0xB8BDA50F ,  0x2802B89E ,
				0x5F058808 ,  0xC60CD9B2 ,  0xB10BE924 ,  0x2F6F7C87 ,  0x58684C11 ,
				0xC1611DAB ,  0xB6662D3D ,  0x76DC4190 ,  0x01DB7106 ,  0x98D220BC ,
				0xEFD5102A ,  0x71B18589 ,  0x06B6B51F ,  0x9FBFE4A5 ,  0xE8B8D433 ,
				0x7807C9A2 ,  0x0F00F934 ,  0x9609A88E ,  0xE10E9818 ,  0x7F6A0DBB ,
				0x086D3D2D ,  0x91646C97 ,  0xE6635C01 ,  0x6B6B51F4 ,  0x1C6C6162 ,
				0x856530D8 ,  0xF262004E ,  0x6C0695ED ,  0x1B01A57B ,  0x8208F4C1 ,
				0xF50FC457 ,  0x65B0D9C6 ,  0x12B7E950 ,  0x8BBEB8EA ,  0xFCB9887C ,
				0x62DD1DDF ,  0x15DA2D49 ,  0x8CD37CF3 ,  0xFBD44C65 ,  0x4DB26158 ,
				0x3AB551CE ,  0xA3BC0074 ,  0xD4BB30E2 ,  0x4ADFA541 ,  0x3DD895D7 ,
				0xA4D1C46D ,  0xD3D6F4FB ,  0x4369E96A ,  0x346ED9FC ,  0xAD678846 ,
				0xDA60B8D0 ,  0x44042D73 ,  0x33031DE5 ,  0xAA0A4C5F ,  0xDD0D7CC9 ,
				0x5005713C ,  0x270241AA ,  0xBE0B1010 ,  0xC90C2086 ,  0x5768B525 ,
				0x206F85B3 ,  0xB966D409 ,  0xCE61E49F ,  0x5EDEF90E ,  0x29D9C998 ,
				0xB0D09822 ,  0xC7D7A8B4 ,  0x59B33D17 ,  0x2EB40D81 ,  0xB7BD5C3B ,
				0xC0BA6CAD ,  0xEDB88320 ,  0x9ABFB3B6 ,  0x03B6E20C ,  0x74B1D29A ,
				0xEAD54739 ,  0x9DD277AF ,  0x04DB2615 ,  0x73DC1683 ,  0xE3630B12 ,
				0x94643B84 ,  0x0D6D6A3E ,  0x7A6A5AA8 ,  0xE40ECF0B ,  0x9309FF9D ,
				0x0A00AE27 ,  0x7D079EB1 ,  0xF00F9344 ,  0x8708A3D2 ,  0x1E01F268 ,
				0x6906C2FE ,  0xF762575D ,  0x806567CB ,  0x196C3671 ,  0x6E6B06E7 ,
				0xFED41B76 ,  0x89D32BE0 ,  0x10DA7A5A ,  0x67DD4ACC ,  0xF9B9DF6F ,
				0x8EBEEFF9 ,  0x17B7BE43 ,  0x60B08ED5 ,  0xD6D6A3E8 ,  0xA1D1937E ,
				0x38D8C2C4 ,  0x4FDFF252 ,  0xD1BB67F1 ,  0xA6BC5767 ,  0x3FB506DD ,
				0x48B2364B ,  0xD80D2BDA ,  0xAF0A1B4C ,  0x36034AF6 ,  0x41047A60 ,
				0xDF60EFC3 ,  0xA867DF55 ,  0x316E8EEF ,  0x4669BE79 ,  0xCB61B38C ,
				0xBC66831A ,  0x256FD2A0 ,  0x5268E236 ,  0xCC0C7795 ,  0xBB0B4703 ,
				0x220216B9 ,  0x5505262F ,  0xC5BA3BBE ,  0xB2BD0B28 ,  0x2BB45A92 ,
				0x5CB36A04 ,  0xC2D7FFA7 ,  0xB5D0CF31 ,  0x2CD99E8B ,  0x5BDEAE1D ,
				0x9B64C2B0 ,  0xEC63F226 ,  0x756AA39C ,  0x026D930A ,  0x9C0906A9 ,
				0xEB0E363F ,  0x72076785 ,  0x05005713 ,  0x95BF4A82 ,  0xE2B87A14 ,
				0x7BB12BAE ,  0x0CB61B38 ,  0x92D28E9B ,  0xE5D5BE0D ,  0x7CDCEFB7 ,
				0x0BDBDF21 ,  0x86D3D2D4 ,  0xF1D4E242 ,  0x68DDB3F8 ,  0x1FDA836E ,
				0x81BE16CD ,  0xF6B9265B ,  0x6FB077E1 ,  0x18B74777 ,  0x88085AE6 ,
				0xFF0F6A70 ,  0x66063BCA ,  0x11010B5C ,  0x8F659EFF ,  0xF862AE69 ,
				0x616BFFD3 ,  0x166CCF45 ,  0xA00AE278 ,  0xD70DD2EE ,  0x4E048354 ,
				0x3903B3C2 ,  0xA7672661 ,  0xD06016F7 ,  0x4969474D ,  0x3E6E77DB ,
				0xAED16A4A ,  0xD9D65ADC ,  0x40DF0B66 ,  0x37D83BF0 ,  0xA9BCAE53 ,
				0xDEBB9EC5 ,  0x47B2CF7F ,  0x30B5FFE9 ,  0xBDBDF21C ,  0xCABAC28A ,
				0x53B39330 ,  0x24B4A3A6 ,  0xBAD03605 ,  0xCDD70693 ,  0x54DE5729 ,
				0x23D967BF ,  0xB3667A2E ,  0xC4614AB8 ,  0x5D681B02 ,  0x2A6F2B94 ,
				0xB40BBE37 ,  0xC30C8EA1 ,  0x5A05DF1B ,  0x2D02EF8D  };
		int c = 0xFFFFFFFF;
		for(int i=0; i < size ;i++){
			c = ((c >> 8 ) & 0x00FFFFFF ) ^ crc32Tab[(int)((c ^ pData[i]) & 0xFF)];
		}
		c ^= 0xFFFFFFFF;
		checksum[0] = (byte) ((c >> 24) & 0xFF);
		checksum[1] = (byte) ((c >> 16) & 0xFF);
		checksum[2] = (byte) ((c >> 8) & 0xFF);
		checksum[3] = (byte) ((c >> 0) & 0xFF);
	}

	public static void Jac_Standard_Safekey(byte [] seed,byte [] key,int [] constkey){
		int i = 0;
		int v0 = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v1 = ((~seed[0])&0xFF) * 0x1000000 + ((~seed[1])&0xFF) * 0x10000 + ((~seed[2])&0xFF) * 0x100 + ((~seed[3])&0xFF);
		int sum = 0,delta = 0x9e3779B9;
		for(i = 0; i < 2; i ++){
			v0 += (((v1 << 4) ^ (v1 >>> 5)) + v1) ^ (sum + constkey[sum & 3]);
			sum += delta;
			v1 += (((v0 << 4) ^ (v0 >>> 5)) + v0) ^ (sum + constkey[(sum >>> 11) & 3]);
		}
		key[0] = (byte) ((v0 >> 24) & 0xFF);
		key[1] = (byte) ((v0 >> 16) & 0xFF);
		key[2] = (byte) ((v0 >> 8) & 0xFF);
		key[3] = (byte) ((v0 >> 0) & 0xFF);
	}

	public static void Zotye_Standard_Safekey(byte[] seed,byte[] key,String mask){
		int unlockseed = 0;
		int undefineseed = 0xFFFFFFFF;
		int seedmask = 0x80000000;
		int algorithmask = 0x4D313231;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		if(mask.equals("A01")){
			algorithmask = 0x41303131;
		}else if(mask.equals("A02")){
			algorithmask = 0x41303231;
		}else if(mask.equals("B01")){
			algorithmask = 0x42303131;
		}else if(mask.equals("B11")){
			algorithmask = 0x42313131;
		}else if(mask.equals("B12")){
			algorithmask = 0x42313231;
		}else if(mask.equals("B15")){
			algorithmask = 0x42313531;
		}else if(mask.equals("B17")){
			algorithmask = 0x42313731;
		}else if(mask.equals("E01")){
			algorithmask = 0x45323231;
		}else if(mask.equals("T22")){
			algorithmask = 0x54323231;
		}else if(mask.equals("S21")){
			algorithmask = 0x53323131;
		}else if(mask.equals("A12")){
			algorithmask = 0x41313231;
		}else if(mask.equals("704")){
			algorithmask = 0x37303431;
		}
		if(!((v_seed == undefineseed) || (v_seed == unlockseed))){
			for(int i = 0; i < 35; i ++){
				if((v_seed & seedmask) != 0){
					v_seed = v_seed <<1;
					v_seed = v_seed ^ algorithmask;
				}else{
					v_seed = v_seed <<1;
				}
			}
		}
		key[0] = (byte) ((v_seed >> 24) & 0xFF);
		key[1] = (byte) ((v_seed>> 16) & 0xFF);
		key[2] = (byte) ((v_seed>> 8) & 0xFF);
		key[3] = (byte) ((v_seed>> 0) & 0xFF);
	}



	//联电标准算法
	public static void LianDian_Standard_SafeKey(byte[] seed, byte[] key){
		int [] constkey = new int[4];
		constkey[0] = 0x4C495551;
		constkey[1] = 0x49534545;
		constkey[2] = 0x444B4559;
		constkey[3] = 0x414C474F;
		int v0 = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v1 = ((~seed[0])&0xFF) * 0x1000000 + ((~seed[1])&0xFF) * 0x10000 + ((~seed[2])&0xFF) * 0x100 + ((~seed[3])&0xFF);
		int sum = 0,delta = 0x9E3779B9;
		for(int i = 0; i < 2; i ++)
		{
			v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + constkey[sum & 3]);
			sum += delta;
			v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + constkey[(sum >> 11) & 3]);
		}
		key[0] = (byte) ((v0 >> 24) & 0xFF);
		key[1] = (byte) ((v0 >> 16) & 0xFF);
		key[2] = (byte) ((v0 >> 8) & 0xFF);
		key[3] = (byte) ((v0 >> 0) & 0xFF);
	}
	//奥易克斯
	public static void Chery_AECS_Standard_SafeKey(byte[] seed, byte[] key){
		int [] constkey = new int[4];
		constkey[0] = 0x6FE2265C;
		constkey[1] = 0x290C4C73;
		constkey[2] = 0xF4678C90;
		constkey[3] = 0xFA220F28;
		int v0 = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		int v1 = ((~seed[0])&0xFF) * 0x1000000 + ((~seed[1])&0xFF) * 0x10000 + ((~seed[2])&0xFF) * 0x100 + ((~seed[3])&0xFF);
		int sum = 0,delta = 0x9E3779B9;
		for(int i = 0; i < 2; i ++)
		{
			v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + constkey[sum & 3]);
			sum += delta;
			v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + constkey[(sum >> 11) & 3]);
		}
		key[0] = (byte) ((v0 >> 24) & 0xFF);
		key[1] = (byte) ((v0 >> 16) & 0xFF);
		key[2] = (byte) ((v0 >> 8) & 0xFF);
		key[3] = (byte) ((v0 >> 0) & 0xFF);
	}
	//奇瑞标准算法
	public static void Chery_Standard_Safekey(byte[] seed,byte[] key){
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x8408;
		int POLYNOM_2 = 0x8025;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2;
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++){
			remainder ^= ((bSeed[n]) << 8);
			for (i = 0; i < 8; i++){
				if ((remainder & TOPBIT) != 0){
					if((remainder & BITMASK) != 0){
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}else{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}else{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}

	public static void CX62B_GBC_Safekey(byte[] seed,byte[] key){
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x4632;
		int POLYNOM_2 = 0x8752;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2;
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++){
			remainder ^= ((bSeed[n]) << 8);
			for (i = 0; i < 8; i++){
				if ((remainder & TOPBIT) != 0){
					if((remainder & BITMASK) != 0){
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}else{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}else{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}

	public static void S61EV_FCM_Safekey(byte[] seed,byte[] key){
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x8409;
		int POLYNOM_2 = 0x8029;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2;
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++){
			remainder ^= ((bSeed[n]) << 8);
			for (i = 0; i < 8; i++){
				if ((remainder & TOPBIT) != 0){
					if((remainder & BITMASK) != 0){
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}else{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}else{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}

	public static void S32EV_ABS_Safekey(byte[] seed, byte[] key){
		int v_key = 0;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		v_key=((((v_seed>>2)^v_seed)<<3)^v_seed);
		key[0] = (byte) ((v_key >> 24) & 0xFF);
		key[1] = (byte) ((v_key >> 16) & 0xFF);
		key[2] = (byte) ((v_key >> 8) & 0xFF);
		key[3] = (byte) ((v_key >> 0) & 0xFF);
	}

	public static boolean Cx62B_FCM_Level2(byte [] seed,byte [] key,long KeyK)
	{
		byte i;
		int temp_key;
		int v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);

		/* Xor with KeyK */
		temp_key = (int) (v_seed ^ KeyK);

		for (i = 0; i < 32 ; i++)
		{
			if ((temp_key & (0x00000001))!= 0)
			{
				temp_key >>>= 1;
				temp_key ^= v_seed;
			}
			else
			{
				temp_key >>>= 1;
				temp_key ^= KeyK;
			}
		}

		/*calculate key*/
		//*key = temp_key;
		key[0] = (byte) ((temp_key >>> 24) & 0xFF);
		key[1] = (byte) ((temp_key >>> 16) & 0xFF);
		key[2] = (byte) ((temp_key >>> 8) & 0xFF);
		key[3] = (byte) ((temp_key >>> 0) & 0xFF);

		/*return calculate status*/
		return true;
	}

	public static void S61EV_BSD_Safekey(byte[] seed,byte[] key,byte[] conskey){
		long []cons = new long[4];
		cons[0] = conskey[0]&0xFF;
		cons[1] = conskey[1]&0xFF;
		cons[2] = conskey[2]&0xFF;
		cons[3] = conskey[3]&0xFF;

		short [] seedarrayByte=new short[4];
		long calkey = 0,coef = 0;

		coef = (cons[0]<<24)+ (cons[1]<<16) + (cons[2]<<8) + cons[3];
		long v_seed = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF);
		seedarrayByte[0] = (short) ((v_seed>>24)& 0xff);
		seedarrayByte[1] = (short)((v_seed>>16)& 0xff);
		seedarrayByte[2] = (short)((v_seed>>8)& 0xff);
		seedarrayByte[3] = (short) ((v_seed>>0)& 0xff);
		seedarrayByte[0] = (short) ((seedarrayByte[0]>>3)|(seedarrayByte[0]<<5));
		seedarrayByte[1] = (short) ((seedarrayByte[1]>>3)|(seedarrayByte[1]<<5));
		seedarrayByte[2] = (short) ((seedarrayByte[2]>>3)|(seedarrayByte[2]<<5));
		seedarrayByte[3] = (short) ((seedarrayByte[3]>>3)|(seedarrayByte[3]<<5));
		seedarrayByte[0] = (short) (((seedarrayByte[0]>>1)&0x55)|((seedarrayByte[0]<<1)&0xAA));
		seedarrayByte[1] = (short) (((seedarrayByte[1]>>1)&0x55)|((seedarrayByte[1]<<1)&0xAA));
		seedarrayByte[2] = (short) (((seedarrayByte[2]>>1)&0x55)|((seedarrayByte[2]<<1)&0xAA));
		seedarrayByte[3] = (short) (((seedarrayByte[3]>>1)&0x55)|((seedarrayByte[3]<<1)&0xAA));
		calkey = ((long)(seedarrayByte[0]<<24)) + ((long)(seedarrayByte[1]<<16))+ ((long)(seedarrayByte[2]<<8)) + ((long)(seedarrayByte[3]));
		calkey = calkey ^ coef;
		key[0] = (byte) ((calkey >>> 24) & 0xFF);
		key[1] = (byte) ((calkey >>> 16) & 0xFF);
		key[2] = (byte) ((calkey >>> 8) & 0xFF);
		key[3] = (byte) ((calkey >>> 0) & 0xFF);
	}

	public static void S61EV_PLG_Safekey(byte[] seed,byte[] key){
		byte [] Xor = {(byte) 0x55,(byte) 0x88,(byte) 0xa7,(byte) 0xc3};
		byte [] Cal = new byte[4];
		for(int k = 0; k < 4; k ++)
			Cal[k] = (byte) (seed[k] ^ Xor[k]);
		key[0] = (byte) (((Cal[0] & 0x0F) << 4) | (Cal[1] & 0xF0));
		key[1] = (byte) (((Cal[1] & 0x0F) << 4) | ((Cal[2] & 0xF0) >> 4));
		key[2] = (byte)((Cal[2] & 0xF0) | ((Cal[3] & 0xF0) >> 4));
		key[3] = (byte) (((Cal[3] & 0x0F) << 4) | (Cal[0] & 0x0F));
	}

	//GAOTIAN SRS安全算法
	public static boolean GaoTian_ABM_Safekey(byte[] seed,byte[] key){
		byte [] Xor = {(byte) 0x55,0x78,0x62,(byte) 0x18};
		byte [] Cal = new byte[4];
		for(int k = 0; k < 4; k ++)
			Cal[k] = (byte) (seed[k] ^ Xor[k]);
		key[0] = (byte) (((Cal[3] & 0x0F) << 4) | (Cal[3] & 0xF0));
		key[1] = (byte) (((Cal[1] & 0x0F) << 4) | ((Cal[0] & 0xF0) >> 4));
		key[2] = (byte)((Cal[1] & 0xF0) | ((Cal[2] & 0xF0) >> 4));
		key[3] = (byte) (((Cal[0] & 0x0F) << 4) | (Cal[2] & 0x0F));
		return true;
	}

	public static void CX62_IMMO_Safekey(byte[]seed, byte[]key, int pin){
		int k[] = {0xBE355A5C, 0xD6952BBE, 0x355A5CD6, 0x952B784E };
		int[] seeds = new int[2];
		seeds[0] = (seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3]&0xFF) * 0x01;
		seeds[1] = (seed[4]&0xFF) * 0x1000000 + (seed[5]&0xFF) * 0x10000 + (seed[6]&0xFF) * 0x100 + (seed[7]&0xFF) * 0x01;
		long z=toUnsigned(seeds[1]), y=toUnsigned(seeds[0]),DELTA=0x9e3779b9,sum=0;
		int p , q ,e;
		if(pin!=0) k[0] ^= pin;
		q = 58;
		while (q-- > 0){
			sum =(sum+DELTA)&0x0FFFFFFFFL;
			e = (int) ((sum >> 2) & 3);
			for (p=0; p<1; p++){
				y = toUnsigned(seeds[1]);
				seeds[0] +=((z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[(p&3^e)]^z));
				z = toUnsigned(seeds[0]);
			}
			y = toUnsigned(seeds[0]);
			seeds[1]+=((z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[(p&3^e)]^z));
			z = toUnsigned(seeds[1]);
		}
		key[0] = (byte) ((seeds[0] >> 24) & 0xFF);
		key[1] = (byte) ((seeds[0] >> 16) & 0xFF);
		key[2] = (byte) ((seeds[0] >> 8) & 0xFF);
		key[3] = (byte) ((seeds[0] >> 0) & 0xFF);
		key[4] = (byte) ((seeds[1] >> 24) & 0xFF);
		key[5] = (byte) ((seeds[1] >> 16) & 0xFF);
		key[6] = (byte) ((seeds[1] >> 8) & 0xFF);
		key[7] = (byte) ((seeds[1] >> 0) & 0xFF);
	}

	static long toUnsigned(int sign){
		return sign&0x0FFFFFFFFL;
	}

	public static void S61EV_MCU_Safekey(byte[] seed,byte[] key){
		int []mask={0x01,0x02,0x400,0x800,0x2000};
		int loop;
		short passes;
		int bSeed =(seed[0]&0xFF) * 0x100 + (seed[1]&0xFF);
		passes=(short)(((bSeed>>8)&0x07)+0x01);
		for(loop=1;loop<=passes;loop++){
			short inc;
			short count=0;
			for(inc=0;inc<5;inc++){
				if(0==(mask[inc]&bSeed)){

				}else{
					count++;
				}
			}
			bSeed=bSeed+(bSeed+(count&0x01));
		}
		key[0] = (byte) ((bSeed>> 8)&0xFF);
		key[1] = (byte) (bSeed & 0xFF);
	}

	//合肥MCU
	public static void hefei_MCU_safekey(byte[] seed,byte[] key)
	{
		int []mask={0x01,0x02,0x400,0x800,0x2000};
		int loop;
		byte passes;
		int bSeed =(seed[0]&0xFF) * 0x100 + (seed[1]&0xFF);
		passes=(byte)(((bSeed>>8)&0x07)+0x01);
		for(loop=1;loop<=passes;loop++){
			byte inc;
			byte count=0;
			for(inc=0;inc<5;inc++){
				if(0==(mask[inc]&bSeed)){

				}else{
					count++;
				}
			}
			bSeed=bSeed+(bSeed+(count&0x01));
		}
		key[0] = (byte) ((bSeed>> 8)&0xFF);
		key[1] = (byte) (bSeed & 0xFF);
	}

	public static void hefei_BCM_safekey(byte[] seed,byte[] key)
	{
		int TOPBIT = 0x8000;
		int POLYNOM_1 = 0x8408;
		int POLYNOM_2 = 0x8025;
		int BITMASK = 0x0080;
		int INITIAL_REMINDER = 0xFFFE;
		int MSG_LEN = 2; /* seed length in bytes */
		byte [] bSeed = new byte[2];
		short remainder;
		byte n;
		byte i;
		bSeed[0] = seed[0]; /* MSB */
		bSeed[1] = seed[1]; /* LSB */
		remainder = (short) INITIAL_REMINDER;
		for (n = 0; n < MSG_LEN; n++)
		{
			/* Bring the next byte into the remainder. */
			remainder ^= ((bSeed[n]) << 8);

			/* Perform modulo-2 division, a bit at a time. */
			for (i = 0; i < 8; i++)
			{
				/* Try to divide the current data bit. */
				if ((remainder & TOPBIT) != 0)
				{
					if((remainder & BITMASK) != 0)
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_1);
					}
					else
					{
						remainder = (short) ((remainder << 1) ^ POLYNOM_2);
					}
				}
				else
				{
					remainder = (short) (remainder << 1);
				}
			}
		}
		key[0] = (byte) ((remainder >>> 8)&0xFF);
		key[1] = (byte) (remainder & 0xFF);
	}


	public static void CX62_EPB_Safekey(byte[]seed,byte [] key){
		byte[] v_mask= {0x15, 0x38, 0x55, 0x77};
		byte[] v_calData  =new byte[4];

		for (int i = 0; i < 4; i++){

			v_calData[i] = (byte) (seed[i] ^ v_mask[i]);
		}
		key[0] = (byte) (((v_calData[3]&0x0F)<<4) | (v_calData[3]&0xF0));
		key[1] = (byte) (((v_calData[1]&0x0F)<<4) | (v_calData[0]&0xF0)>>4);
		key[2] = (byte) ((v_calData[1]&0xF0)|((v_calData[2]&0xF0)>>4));
		key[3] = (byte) (((v_calData[0]&0x0F)<<4)|(v_calData[2]&0x0F));
	}

	public static void CX62B_FCM_Safekey(byte[] seed, byte[] key){
		long temp_key;
		long KeyK = 0x000029D6;
		int v_seed = (seed[0]&0Xff)*0x1000000 + (seed[1]&0Xff)*0x10000 + (seed[2]&0Xff)*0x100 + (seed[3]&0Xff);
		long seeds = v_seed & 0x0FFFFFFFFL;
		temp_key = seeds ^ KeyK;
		for(int i = 0; i < 32 ;i++){
			if ((temp_key & (0x1))!= 0){
				temp_key = ( temp_key << 3 ) | ( temp_key >> 29 ) & 0x0FFFFFFFFL;
				temp_key  = (temp_key ^ seeds)& 0x0FFFFFFFFL;
			}else{
				temp_key = ( temp_key >> 7 ) | ( temp_key << 25 ) & 0x0FFFFFFFFL;
				temp_key = (temp_key ^ KeyK)& 0x0FFFFFFFFL;
			}
		}
		key[0] = (byte) ((temp_key >> 24) & 0xFF);
		key[1] = (byte) ((temp_key >> 16) & 0xFF);
		key[2] = (byte) ((temp_key >> 8) & 0xFF);
		key[3] = (byte) ((temp_key >> 0) & 0xFF);
	}
	public static void CX62C_TCU_Safekey1(byte[] seed, byte[] key){
		long temp_key;
		long KeyK = 0x000023DC;
		int v_seed = (seed[0]&0Xff)*0x1000000 + (seed[1]&0Xff)*0x10000 + (seed[2]&0Xff)*0x100 + (seed[3]&0Xff);
		long seeds = v_seed & 0x0FFFFFFFFL;
		temp_key = seeds ^ KeyK;
		for(int i = 0; i < 32 ;i++){
			if ((temp_key & (0x1))!= 0){
				temp_key = ( temp_key << 3 ) | ( temp_key >> 29 ) & 0x0FFFFFFFFL;
				temp_key  = (temp_key ^ seeds)& 0x0FFFFFFFFL;
			}else{
				temp_key = ( temp_key >> 7 ) | ( temp_key << 25 ) & 0x0FFFFFFFFL;
				temp_key = (temp_key ^ KeyK)& 0x0FFFFFFFFL;
			}
		}
		key[0] = (byte) ((temp_key >> 24) & 0xFF);
		key[1] = (byte) ((temp_key >> 16) & 0xFF);
		key[2] = (byte) ((temp_key >> 8) & 0xFF);
		key[3] = (byte) ((temp_key >> 0) & 0xFF);
	}
	public static void CX62C_TCU_Safekey4(byte[] seed, byte[] key){
		long temp_key;
		long KeyK = 0x0000638F;
		int v_seed = (seed[0]&0Xff)*0x1000000 + (seed[1]&0Xff)*0x10000 + (seed[2]&0Xff)*0x100 + (seed[3]&0Xff);
		long seeds = v_seed & 0x0FFFFFFFFL;
		temp_key = seeds ^ KeyK;
		for(int i = 0; i < 32 ;i++){
			temp_key = ( temp_key << 7 ) | ( temp_key >> 25 ) & 0x0FFFFFFFFL;
			temp_key = (temp_key ^ KeyK)& 0x0FFFFFFFFL;
		}
		key[0] = (byte) ((temp_key >> 24) & 0xFF);
		key[1] = (byte) ((temp_key >> 16) & 0xFF);
		key[2] = (byte) ((temp_key >> 8) & 0xFF);
		key[3] = (byte) ((temp_key >> 0) & 0xFF);
	}
	public static void CX62B_FRM_Safekey(byte[] seed, byte[] key){
		long KeyK = 0x00005600;
		int v_seed = (seed[0]&0Xff)*0x1000000 + (seed[1]&0Xff)*0x10000 + (seed[2]&0Xff)*0x100 + (seed[3]&0Xff);
		long seeds = toUnsigned(v_seed);
		long temp_key = (seeds ^ KeyK );
		for (int i = 0; i < 32 ; i++){
			if ((temp_key & (0x00000001))!= 0){
				temp_key = (temp_key >> 1) & 0x0FFFFFFFFL;
				temp_key = (temp_key ^ seeds) & 0x0FFFFFFFFL;
			}else{
				temp_key = (temp_key >> 1) & 0x0FFFFFFFFL;
				temp_key = (temp_key ^ KeyK) & 0x0FFFFFFFFL;
			}
		}
		key[0] = (byte) ((temp_key >>> 24) & 0xFF);
		key[1] = (byte) ((temp_key >>> 16) & 0xFF);
		key[2] = (byte) ((temp_key >>> 8) & 0xFF);
		key[3] = (byte) ((temp_key >>> 0) & 0xFF);
	}

	public static void CX62B_TCM_Safekey(byte[] seed, byte[] key){
		int seeds =(seed[0]&0xFF) * 0x1000000 + (seed[1]&0xFF) * 0x10000 + (seed[2]&0xFF) * 0x100 + (seed[3] &0xFF);
		long v_seed = toUnsigned(seeds);
		long seedTemp1 = v_seed, seedTemp2 = (~v_seed & 0x0FFFFFFFFL);
		int sum = 0, delta = 0x0AB01000;
		int [] k = new int[4];
		k[0]=0x4C495551;
		k[1]=0x49534545;
		k[2]=0x444b4559;
		k[3]=0x414c474f;
		for(int i=0; i < 2; i++){
			seedTemp1 = (seedTemp1 + ((((seedTemp2<<4)^(seedTemp2>>5))+seedTemp2)^(sum+k[(sum & 3)]))) & 0x0FFFFFFFFL;;
			sum += delta;
			seedTemp2 = (seedTemp2 + ((((seedTemp1<<4)^(seedTemp1>>5))+seedTemp1)^(sum+k[((sum>>11)&3)]))) & 0x0FFFFFFFFL;
		}
		key[0] = (byte) ((seedTemp1 >> 24) & 0xFF);
		key[1] = (byte) ((seedTemp1 >> 16) & 0xFF);
		key[2] = (byte) ((seedTemp1 >> 8) & 0xFF);
		key[3] = (byte) ((seedTemp1 >> 0) & 0xFF);
	}
	public static void Chery_KQ5_YaTai_Abs(byte[] seed, byte[] key)
	{
		for(int k = 0;k < 4; k ++)
			key[k] = (byte) (seed[k] + 0x19);
	}
	public static void chery_ling_safekey(byte[] seed,byte[] key)
	{
		long Sd = (seed[0] & 0xFF) * 0x1000000 + (seed[1] & 0xFF) * 0x10000 + (seed[2] & 0xFF) * 0x100 + (seed[3] & 0xFF);
		long K1 = 542712;
		long K2 = 2567;
		long A,B;
		A = (K2 * Sd) + K1;
		B = (K2 * Sd) - K1;
		long Ky = A ^ B;
		key[0] = (byte) ((Ky >>> 24) & 0xFF);
		key[1] = (byte) ((Ky >>> 16) & 0xFF);
		key[2] = (byte) ((Ky >>> 8) & 0xFF);
		key[3] = (byte) ((Ky >>> 0) & 0xFF);
	}
	public static void chery_ECU_safekey7(byte[] seed,byte[] key){
		long temp_key;
		long KeyK = 0x000038E7;
		int v_seed = (seed[0]&0Xff)*0x1000000 + (seed[1]&0Xff)*0x10000 + (seed[2]&0Xff)*0x100 + (seed[3]&0Xff);
		long seeds = v_seed & 0x0FFFFFFFFL;
		temp_key = seeds ^ KeyK;
		for (int i=0;i<32;i++){
			temp_key=((temp_key<<7)|(temp_key>>25) )& 0x0FFFFFFFFL;
			temp_key = (temp_key ^ KeyK)& 0x0FFFFFFFFL;
		}
		key[0] = (byte) ((temp_key >> 24) & 0xFF);
		key[1] = (byte) ((temp_key >> 16) & 0xFF);
		key[2] = (byte) ((temp_key >> 8) & 0xFF);
		key[3] = (byte) ((temp_key >> 0) & 0xFF);
	}
}
